package com.magold.touch;

import org.andengine.entity.scene.Scene;
import org.andengine.input.touch.TouchEvent;

import android.util.FloatMath;

public class MagoldClickDetector extends BaseDirectable implements IClickDector {
	public static final float DEFAULT_MAX_TRIGGER_MS = 200;
	public static final float DEFAULT_MAX_DISTANCE = 20;
	
	private float mMaxTriggerMilliSeconds;
	private float mMaxDistance;
	private IClickListener mListener;
	
	public MagoldClickDetector() {
		this(DEFAULT_MAX_TRIGGER_MS, DEFAULT_MAX_DISTANCE, null);
	}
	
	public MagoldClickDetector(float pMaxTriggerMilliSeconds, float pMinDistance) {
		this(pMaxTriggerMilliSeconds, pMinDistance, null);
	}
	
	public MagoldClickDetector(IClickListener pListener) {
		this(DEFAULT_MAX_TRIGGER_MS, DEFAULT_MAX_DISTANCE, pListener);
	}
	
	public MagoldClickDetector(float pMaxTriggerMilliSeconds, float pMinDistance, IClickListener pListener) {
		mMaxTriggerMilliSeconds = pMaxTriggerMilliSeconds;
		mMaxDistance = pMinDistance;
		mListener = pListener;
		
		resetTemplate();
	}
	
	private long mDownTimeMilliseconds;
	private int mPointerID;
	private float mDownTimeX;
	private float mDownTimeY;
	@Override
	public boolean onManagedDetecting(Scene pScene, TouchEvent pEvent) {
		switch(pEvent.getAction()) {
		case TouchEvent.ACTION_DOWN:
			if (mPointerID != TouchEvent.INVALID_POINTER_ID) {
				skipCurrEvent();
			} else {
				prepareClick(pEvent);
			}
			break;
		case TouchEvent.ACTION_UP:
		case TouchEvent.ACTION_CANCEL:
		case TouchEvent.ACTION_OUTSIDE:
			if(mPointerID != TouchEvent.INVALID_POINTER_ID && checkClick(pEvent)) {
				if (mListener != null) {
					mListener.onClick(pScene, this, pEvent.getX(), pEvent.getY());
				}
				mPointerID = TouchEvent.INVALID_POINTER_ID;
				return true;
			}
			break;
		}
		
		return false;
	}

	protected void prepareClick(TouchEvent pEvent) {
		mDownTimeMilliseconds = pEvent.getMotionEvent().getEventTime();
		mPointerID = pEvent.getPointerID();
		mDownTimeX = pEvent.getX();
		mDownTimeY = pEvent.getY();
	}

	protected boolean checkClick(TouchEvent pSceneTouchEvent) {
		long mUpTimeMilliseconds = pSceneTouchEvent.getMotionEvent().getEventTime();
		float dX = pSceneTouchEvent.getX() - mDownTimeX;
		float dY = pSceneTouchEvent.getY() - mDownTimeY;

		return (mUpTimeMilliseconds - mDownTimeMilliseconds <= mMaxTriggerMilliSeconds &&
				mPointerID == pSceneTouchEvent.getPointerID() &&
				mMaxDistance >= FloatMath.sqrt(dX * dX + dY * dY));
	}
	
	@Override
	public void resetTemplate() {
		mDownTimeMilliseconds = 0;
		mPointerID = TouchEvent.INVALID_POINTER_ID;
		mDownTimeX = 0;
		mDownTimeY = 0;
	}

	@Override
	public void setDetecorListener(IDetectorListener pListener) {
		setClickListener((IClickListener) pListener);
	}

	@Override
	public IDetectorListener getDetectorListener() {
		return mListener;
	}

	@Override
	public void setLimits(float pMaxTriggerMilliSeconds, float pMinDistance) {
		mMaxTriggerMilliSeconds = pMaxTriggerMilliSeconds;
		mMaxDistance = pMinDistance;
	}

	@Override
	public float getMaxTriggerMilliSeconds() {
		return mMaxTriggerMilliSeconds;
	}

	@Override
	public float getMinDistance() {
		return mMaxDistance;
	}

	@Override
	public void setClickListener(IClickListener pListener) {
		mListener = pListener;
	}

}
